#include "MWFile.h"
#include "MWDebug.h"

#include <io.h>

#ifdef MW_PLATFORM_WIN32
#include <windows.h>

#pragma warning(push)
#pragma warning(disable : 4999)
#pragma warning(disable : 4996)
#pragma warning(disable : 4267)

#endif



using namespace Myway;

const char File::ENDL('\n');


File::File() : mHandle(NULL), mFile(""), mEof(true)
{
}

File::~File()
{
    Close();
}

void _makeDir(const char * filedir)
{
#ifdef MW_PLATFORM_WIN32

	TString128 dir = filedir;

	if (dir == "")
		return ;

	SECURITY_ATTRIBUTES attribute;
	attribute.nLength = sizeof(attribute);
	attribute.lpSecurityDescriptor = NULL;
	attribute.bInheritHandle = FALSE;

	if (!FileHelper::Exist(dir))
	{
		TString128 _dir = FileHelper::GetFileDir(dir);
		_makeDir(_dir.c_str());

		BOOL hr = CreateDirectory(dir.c_str(), &attribute);

		d_assert (hr == TRUE);
	}

#else

#endif
}

bool File::Open(const char * file, OPEN_MODE mode)
{
	Close();

	/*if (mode == OM_WRITE ||
		mode == OM_WRITE_BINARY)
	{
		_makeDir(FileHelper::GetFileDir(file).c_str());
	}*/

	switch (mode)
	{
	case OM_READ:
		mHandle = fopen(file,"r");
		break;

	case OM_WRITE:
		mHandle = fopen(file, "w");
		break;

	case OM_APPEND:
		mHandle = fopen(file, "a");
		break;

	case OM_READ_WRITE:
		mHandle = fopen(file, "w+");
		break;

	case OM_READ_WRITE_APPEND:
		mHandle = fopen(file, "a+");
		break;

    case OM_READ_BINARY:
        mHandle = fopen(file, "rb");
        break;

    case OM_WRITE_BINARY:
        mHandle = fopen(file, "wb");
        break;

    case OM_APPEND_BINARY:
        mHandle = fopen(file, "ab");
        break;

    case OM_READ_WRITE_BINARY:
        mHandle = fopen(file, "r+b");
        break;

    case OM_READ_WRITE_APPEND_BINARY:
        mHandle = fopen(file, "a+b");
        break;
	}

	mFile = file;
	mMode = mode;
    mEof = false;
	return mHandle != NULL;
}

bool File::IsOpen()
{
    return mHandle != NULL;
}

void File::Close()
{
	if (mHandle)
	{
		fflush(mHandle);
		fclose(mHandle);
		mHandle = 0;
	}
}

bool File::Skip(int offset)
{
	d_assert(mHandle);

	return !fseek(mHandle, offset, SEEK_CUR);
}

bool File::Seek(int pos)
{
	d_assert(mHandle);

	return !fseek(mHandle, pos, SEEK_SET);
}

int File::Position()
{
	d_assert(mHandle);

	return ftell(mHandle);
}

int File::Size()
{
	d_assert(mHandle);

	int cur = ftell(mHandle);
	fseek(mHandle, 0, SEEK_END);
	int size = ftell(mHandle);
	fseek(mHandle, cur, SEEK_SET);
	return size;
}

void File::Flush()
{
    d_assert(mHandle);

    fflush(mHandle);
}

int File::Write(const void * data, int esize, int count)
{
    d_assert(mHandle);

    return fwrite(data, esize, count, mHandle);
}

int File::Read(void * data, int esize, int count)
{
    d_assert(mHandle);

    int read_count = fread(data, esize, count, mHandle);
    mEof = (read_count != count);
    return read_count;
}

bool File::eof()
{
    return mEof;
}

const TString128 & File::FileName()
{
    return mFile;
}


#ifdef  MW_PLATFORM_WIN32
#pragma warning(pop)
#endif

TString128 FileHelper::GetExternName(const TString128 & file)
{
    int len = file.Length();
    const char * str = file.c_str();

    while (len > 0 && str[len - 1] != '.')
        len -= 1;

    if (len < 1 || str[len - 1] != '.')
        return "";

    return &str[len];
}

TString128 FileHelper::GetFileDir(const TString128 & file)
{
	const char * str = file.c_str();
	int len = file.Length();

	while (len > 0 && (str[len - 1] != '\\' && str[len - 1] != '/'))
		--len;

	TString128 dir = file;

	dir[len] = 0;

	if (len > 0)
		dir[len - 1] = 0;

	return dir;
}

TString128 FileHelper::GetBaseName(const TString128 & file)
{
	const char * str = file.c_str();
	int len = file.Length();
	int kLen = len;

	while (len > 0 && (str[len - 1] != '\\' && str[len - 1] != '/'))
		--len;

	char baseName[128];

	int i = 0;
	while (len < kLen)
	{
		baseName[i++] = str[len++];
	}
	
	baseName[i] = 0;

	return baseName;
}

TString128 FileHelper::RemoveExternName(const TString128 & file)
{
    int len = file.Length();
    const char * str = file.c_str();
    int p = len;

    while (p > 0 && str[p - 1] != '.')
        p -= 1;

    if (p < 1 || str[p - 1] != '.')
        return file;

    char txt[128];

    Strcpy(txt, 128, file.c_str(), 128);

    txt[p - 1] = 0;

    return txt;
}

bool FileHelper::Exist(const TString128 & file)
{
	return ::_access(file.c_str(), 0) != -1;
}